package XMFramework.Core
{
	public class SAMFObject
	{
		private var rawData:*			=	null;
		private var cookData:Object		=	null;
		private var messageId:int		=	0;
		
		public function SAMFObject( msgId:int, data:Object )
		{
			messageId	=	msgId;
			rawData		=	data;			
			cookData	=	cookParams( data );
		}
		
		public function getRawData():*
		{
			return rawData;
		}
		
		public function getVar( str:String, omitNULLVariable:Boolean = false ):*
		{
			var r:*	=	digVariable( str );
			if( omitNULLVariable == false && r == null )
				throwNULLError();
			
			return r;
		}		
		
		public function getObject( str:String, omitNULLVariable:Boolean = false ):SAMFObject
		{
			var r:*	=	digVariable( str );
			if( omitNULLVariable == false && r == null )
				throwNULLError();
			
			return r;
		}		
	
		public function getInt( str:String, omitNULLVariable:Boolean = false ):int
		{
			var r:*	=	digVariable( str );
			if( omitNULLVariable == false && r == null )
				throwNULLError();
			
			if( !(r is int) )
				throwTypeError( str, "int", r);
			
			return r as int;
		}
		
		public function getNumber( str:String, omitNULLVariable:Boolean = false ):Number
		{
			var r:*	=	digVariable( str );
			if( omitNULLVariable == false && r == null )
				throwNULLError();
			
			if( !(r is Number) )
				throwTypeError( str, "Number", r);
			
			return r as Number;
		}
		   
		public function getBoolean( str:String, omitNULLVariable:Boolean = false ):Boolean
		{
			var r:*	=	digVariable( str );
			if( omitNULLVariable == false && r == null )
				throwNULLError();
			
			if( !(r is Boolean) )
				throwTypeError( str, "Boolean", r);
			
			return r as Boolean;
		}
		
		public function getArray( str:String, omitNULLVariable:Boolean = false ):Array
		{
			var r:*	=	digVariable( str );
			if( omitNULLVariable == false && r == null )
				throwNULLError();
			
			if( !(r is Array) )
				throwTypeError( str, "Array", r);
			
			return r as Array;
		}
		
		public function getString( str:String, omitNULLVariable:Boolean = false ):String
		{
			var r:*	=	digVariable( str );
			if( omitNULLVariable == false && r == null )
				throwNULLError();
			
			if( !(r is String) )
				throwTypeError( str, "String", r);
			
			return r as String;
		}
		
		/////////////////////////////
		private function throwTypeError( str:String, expectType:String, param:* ):void
		{
			throw new SError( SError.ERR_SERVER_ERROR, null, "msgId: " + messageId + " - Data type error: ["+digType(param)+"] expected ["+expectType+"] at {"+str+"}");
		}
		
		private function throwNULLError( str:String ):void
		{
			throw new SError( SError.ERR_SERVER_ERROR, null, "msgId: " + messageId + " - NULL data at {"+str+"}" );
		}
		
		private function digVariable( str:String ):*
		{			
			var keys:Array	=	str.split( "." );
			var seek:Object	=	rawData;
			
			for( var i:int=0; i<keys.length; i++ )
			{
				if( seek.hasOwnProperty( keys[i] ) )
					seek	=	seek[keys[i]];
				
				else
					return null;
			}
			
			return seek;
		}
		
		private static function cookParams( rawData:* ):SAMFObject
		{
			var params:Object	=	new Object();
//			for( var i:String in rawData )
//			{
//				if( rawData[i] is Object || rawData[i] is Array )
//				{
//					
//				}
//				else
//					cookData[]
//			}
			return params;
		}
		
		private function digType( params:* ):String
		{
			if( params == null )
				return "null";
			
			else if( params is int )
				return "int";
			
			else if( params is uint )
				return "uint";
			
			else if( params is Number )
				return "Number";
			
			else if( params is Boolean )
				return "Boolean";
			
			else if( params is Array )
				return "Array";
			
			else if( params is String )
				return "String";
			
			else if( params is Object )
				return "Object";

			return "Undefined";
		}
	}
}